JavaScript 中的 this
在 ECAMScript 规范中,这样定义 this
this 关键字执行为当前执行环境的 ThisBinding
在 MDN 中这样解释 this
在绝大多数情况下,函数的调用方式决定了 this 的值。
可以这样理解,在 JavaScript 中 this 的指向是调用时决定的,而不是在创建时决定的。如此一来,JavaScript 的 this 指向具有一定的迷惑性,简而言之,JavaScript 的 this 具有运行时绑定的特性。
全局执行上下文中的 this
全局执行上下文(任何函数外部)中的 this 指向全局对象。
// 在浏览器中全局执行上下文是 window 对象
console.log(this === window) // true
this.a = '1997'
console.log(this.a === window.a) // true
console.log(a, this.a, window.a) // 1 1 1
函数执行上下文中的 this
在函数内部的 this 指向,取决于函数调用的方式。
直接调用
在非严格模式下,this 指向全局对象
function fn() {
console.log(this === window) // true
console.log(this) // Window {TEMPORARY: 0, PERSISTENT: 1, Symbol(Symbol.toStringTag): "Window", constructor: ƒ}
}
fn() // true
在严格模式下,如果 this 没有被执行环境定义,则保持为 undefined
,如以下代码,第一个例子中的全局函数是直接调用则 this 为 undefined,第二个例子全局对象作为 window 对象的方法调用,则 this 为 window。
function fn() {
'use strict'
console.log(this === window) // false
console.log(this) // undefined
}
fn()
function fn() {
'use strict'
console.log(this === window) // true
console.log(this) // Window {TEMPORARY: 0, PERSISTENT: 1, Symbol(Symbol.toStringTag): "Window", constructor: ƒ}
}
window.fn()
作为对象的方法调用
当函数作为对象的方法调用时,函数的 this 是调用该函数的对象。
如下列代码,fn 作为对象 obj 的一个方法来调用,this 的指向便是调用这个方法的对象 obj。
var value = 1943
const obj = {
value: 1997,
fn: function () {
console.log(this.value) // 1997
}
}
obj.fn()
但值得一提的是,下列代码中的 fn 函数又被赋值给 fn2,fn2 直接调用,this 指向 window(浏览器中),所以打印的值为 1943
var value = 1943
const obj = {
value: 1997,
fn: function () {
console.log(this.value) // 1997
}
}
const fn2 = obj.fn
fn2()
call()、apply()
使用 call() 或 apply() 方法改变函数的执行上下文,函数的 this 指向为传入的执行上下文。
var value = 100
var Person = {
value: 200
}
function fn() {
console.log(this.value)
}
fn() // 100
fn.call(Person) // 200
fn.apply(Person) // 200
bind()
使用 bind() 方法改变 this 的指向,和 call()、apply() 类似,使用 bind 绑定 this 的函数,this 永远指向 bind 方法绑定的第一个参数,无论何时调用。
function fn() {
console.log(this.value)
}
var fn2 = fn.bind({
value: 100
})
var obj = {
value: 200,
fn: fn2
}
fn2() // 100
obj.fn() // 100
构造函数
作为构造函数,this 永久绑定在正在构造的对象上。
function Person() {
this.age = 18
}
const p = new Person()
console.log(p.age) // 18
箭头函数
箭头函数没有自己的 this ,其 this 指向外层非箭头函数的一个执行环境。
在 MDN 中有这样的描述:
箭头函数会捕获其所在上下文的this值,作为自己的this值。
可以这样理解:箭头函数没有 this,在箭头函数中使用 this 将会沿着作用域链寻找 this。
(() => {
// 浏览器中
console.log(this === window) // true
})()
var value = 0
var obj = {
value: 1,
fn: () => {
console.log(this.value)
}
}
obj.fn() // 0
作为一个 DOM 事件处理函数
当函数作为 DOM 的事件处理函数时,this 指向触发这个事件的 DOM 元素。
const $div = document.createElement('div')
$div.setAttribute('id', 1997)
$div.addEventListener('click', function() {
console.log(this) // <div id="1997></div>
console.log(this.getAttribute('id')) // 1997
})
$div.click()